package com.boil.qz.safekavass.weixin.service;

import com.alibaba.fastjson.JSONObject;
import com.boil.qz.safekavass.model.WeixinUser;
import com.boil.qz.safekavass.repository.WeixinUserRepository;
import com.boil.qz.safekavass.weixin.WeixinException.WeixinException;
import com.boil.qz.safekavass.weixin.model.reply.TextMsg;
import com.boil.qz.safekavass.weixin.util.WeixinUtils;
import com.boil.util.Constants;
import com.boil.util.DateUtils;
import com.boil.util.Utils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;

/**
 * Created by ChenYong on 2017-04-27.
 * <br>
 * 微信接入 Service。
 */
@Service
public class AccessService {
    /**
     * 日志
     */
    private static Logger log = LoggerFactory.getLogger(AccessService.class);
    /**
     * 微信用户 Service
     */
    @Autowired
    private WeixinUserRepository weixinUserRepository;

    /**
     * 处理接入。
     *
     * @param request 来自微信服务器的请求。
     * @return 响应微信服务器的数据
     */
    public String doAccess(HttpServletRequest request) {
        // 回复消息
        String replyMsg = Constants.EMPTY_STR;
        // 回复文本消息
        TextMsg replyTextMsg = new TextMsg();

        if (request != null) {
            // 获取时间戳
            String timestamp = request.getParameter(WeixinUtils.TIMESTAMP_STR);
            // 获取随机数
            String nonce = request.getParameter(WeixinUtils.NONCE_STR);
            // 获取加密类型
            String encryptType = request.getParameter(WeixinUtils.ENCRYPT_TYPE_STR);
            // 获取消息加密签名
            String msgSignature = request.getParameter(WeixinUtils.MSG_SIGNATURE_STR);
            // Xml 明文消息 Map
            Map<String, String> xmlDecryptMsgMap = null;
            // 公众账号
            String toUserName = Constants.EMPTY_STR;
            // openid
            String fromUserName = Constants.EMPTY_STR;
            // 消息类型
            String msgType = Constants.EMPTY_STR;
            /*
             * 加密标记：true-加密；false-未加密。
             * 判断公众账号的加密模式：<br>
             * 1、明文模式（默认）：消息未加密；
             * 2、兼容模式：有未加密消息和已加密消息；
             * 3、安全模式（推荐）：消息已加密。
             */
            boolean encryptFlag = false;
            // 当前时间
            Date currDate = new Date();

            if (StringUtils.isNotBlank(encryptType) && WeixinUtils.ENCRYPT_TYPE_AES.equals(encryptType)) {
                encryptFlag = true;
            }

            try {
                // 安全模式
                if (encryptFlag) {
                    // 解析微信服务器请求(POST)中的 XML 字符串
                    Map<String, String> xmlEncryptMsgMap = Utils.xml2Map(request.getInputStream());
                    // 获取密文消息
                    String encryptMsg = xmlEncryptMsgMap.get(WeixinUtils.ENCRYPT_STR);
                    // 解密，得到微信指定格式的 XML 字符串，这就是明文消息
                    String xmlDecryptMsg = WeixinUtils.decryptMsg(msgSignature, timestamp, nonce, encryptMsg);

                    xmlDecryptMsgMap = Utils.xml2Map(xmlDecryptMsg);

                    // 明文模式
                } else {
                    xmlDecryptMsgMap = Utils.xml2Map(request.getInputStream());
                }

                // 获取公众账号
                toUserName = xmlDecryptMsgMap.get(WeixinUtils.TO_USER_NAME_STR);
                // 获取 openid
                fromUserName = xmlDecryptMsgMap.get(WeixinUtils.FROM_USER_NAME_STR);
                // 获取消息类型
                msgType = xmlDecryptMsgMap.get(WeixinUtils.MSG_TYPE_STR);

                log.info("微信接入Service--->openid[{}]给公众账号[{}]发送的消息：{}", fromUserName, toUserName, xmlDecryptMsgMap);

                // 设置文本消息的属性
                replyTextMsg.setToUserName(fromUserName);
                replyTextMsg.setFromUserName(toUserName);
                replyTextMsg.setCreateTime(currDate.getTime());
                replyTextMsg.setMsgType(WeixinUtils.MSG_TYPE_TEXT);

                // 消息处理开始了，判断消息类型
                // 文本消息
                if (WeixinUtils.MSG_TYPE_TEXT.equals(msgType)) {

                    // 图片消息
                } else if (WeixinUtils.MSG_TYPE_IMAGE.equals(msgType)) {

                    // 语音消息
                } else if (WeixinUtils.MSG_TYPE_VOICE.equals(msgType)) {

                    // 视频消息
                } else if (WeixinUtils.MSG_TYPE_VIDEO.equals(msgType)) {

                    // 小视频消息
                } else if (WeixinUtils.MSG_TYPE_SHORTVIDEO.equals(msgType)) {

                    // 地理位置消息
                } else if (WeixinUtils.MSG_TYPE_LOCATION.equals(msgType)) {

                    // 链接消息
                } else if (WeixinUtils.MSG_TYPE_LINK.equals(msgType)) {

                    // 事件消息
                } else if (WeixinUtils.MSG_TYPE_EVENT.equals(msgType)) {
                    // 事件类型
                    String eventType = xmlDecryptMsgMap.get(WeixinUtils.EVENT_TYPE_STR);

                    // 关注事件
                    if (WeixinUtils.EVENT_TYPE_SUBSCRIBE.equals(eventType)) {
                        // 根据 openid 查询微信用户
                        WeixinUser weixinUser = weixinUserRepository.findByOpenid(fromUserName);
                        // 微信服务器上的用户基本信息
                        JSONObject weixinUserJSONObject = null;

                        try {
                            // 根据 openid 获取微信服务器上的用户基本信息
                            weixinUserJSONObject = WeixinUtils.sendHttpsGet(String.format(WeixinUtils.URL_GET_USER_INFO, WeixinUtils.ACCESS_TOKEN, fromUserName));

                            log.info("微信接入Service--->openid[{}]获取微信服务器上的用户基本信息：{}", fromUserName, weixinUserJSONObject.toJSONString());
                        } catch (WeixinException e) {
                            log.error("微信接入Service--->openid[{}]获取微信服务器上的用户基本信息时出现异常：{}", fromUserName, e);
                        }

                        // 未关注
                        if (weixinUser == null) {
                            weixinUser = new WeixinUser();
                            weixinUser.setOpenid(fromUserName);
                        }

                        weixinUser.setUnsubscribeTime(null);

                        // 获取成功
                        if ((weixinUserJSONObject != null) && StringUtils.isBlank(weixinUserJSONObject.getString(WeixinUtils.ERRCODE_STR))) {
                            weixinUser.setSubscribe(weixinUserJSONObject.getIntValue(WeixinUtils.SUBSCRIBE_STR));
                            weixinUser.setNickname(weixinUserJSONObject.getString(WeixinUtils.NICKNAME_STR));
                            weixinUser.setSex(weixinUserJSONObject.getIntValue(WeixinUtils.SEX_STR));
                            weixinUser.setLanguage(weixinUserJSONObject.getString(WeixinUtils.LANGUAGE_STR));
                            weixinUser.setCity(weixinUserJSONObject.getString(WeixinUtils.CITY_STR));
                            weixinUser.setProvince(weixinUserJSONObject.getString(WeixinUtils.PROVINCE_STR));
                            weixinUser.setCountry(weixinUserJSONObject.getString(WeixinUtils.COUNTRY_STR));
                            weixinUser.setHeadimgurl(weixinUserJSONObject.getString(WeixinUtils.HEADIMGURL_STR));
                            weixinUser.setSubscribeTime(new Date(weixinUserJSONObject.getLongValue(WeixinUtils.SUBSCRIBE_TIME_STR) * Constants.VALUE_L_1000));
                            weixinUser.setUnionid(weixinUserJSONObject.getString(WeixinUtils.UNIONID_STR));
                            weixinUser.setRemark(weixinUserJSONObject.getString(WeixinUtils.REMARK_STR));
                            weixinUser.setGroupid(weixinUserJSONObject.getLongValue(WeixinUtils.GROUPID_STR));
                        }

                        // 未关注
                        if (weixinUser.getId() == null) {
                            weixinUserRepository.save(weixinUser);
                        }

                        StringBuffer subscribeMsgSb = new StringBuffer();
                        subscribeMsgSb.append("\ue304您好！");
                        subscribeMsgSb.append("\n");
                        subscribeMsgSb.append("欢迎关注清镇市安全生产监督管理局的官方微信号【清镇安监卫士】，您可以在这里进行举报信息提交，获取最新安监新闻等等。");

                        if (StringUtils.isBlank(weixinUser.getPhone())) {
                            subscribeMsgSb.append("\n");
                            subscribeMsgSb.append("\n");
                            subscribeMsgSb.append("您未绑定手机号，点击菜单【绑定手机号】进行绑定。");
                        } else {
                            subscribeMsgSb.append("\n");
                            subscribeMsgSb.append("\n");
                            subscribeMsgSb.append(String.format("您已绑定手机号：%s。", weixinUser.getPhone()));
                        }

                        replyTextMsg.setContent(subscribeMsgSb.toString());

                        // 安全模式
                        if (encryptFlag) {
                            replyMsg = WeixinUtils.encryptMsg(WeixinUtils.msg2Xml(replyTextMsg), timestamp, nonce);

                            // 明文模式
                        } else {
                            replyMsg = WeixinUtils.msg2Xml(replyTextMsg);
                        }

                        // 用户已关注时，扫描二维码事件
                    } else if (WeixinUtils.EVENT_TYPE_SCAN.equals(eventType)) {

                        // 取消关注事件
                    } else if (WeixinUtils.EVENT_TYPE_UNSUBSCRIBE.equals(eventType)) {
                        WeixinUser weixinUser = weixinUserRepository.findByOpenid(fromUserName);
                        weixinUser.setSubscribe(Constants.VALUE_0);
                        weixinUser.setSubscribeTime(null);
                        weixinUser.setUnsubscribeTime(DateUtils.getCurrDate());

                        // 上报地理位置事件
                    } else if (WeixinUtils.EVENT_TYPE_LOCATION.equals(eventType)) {

                        // 自定义菜单事件
                    } else if (WeixinUtils.EVENT_TYPE_CLICK.equals(eventType)) {

                    }
                }

                log.info("微信接入Service--->公众账号[{}]给openid[{}]回复的消息--->{}", toUserName, fromUserName, replyMsg);
            } catch (Exception e) {
                log.error("微信接入Service--->处理来自微信服务器的请求(POST)出现异常：{}", e);

                replyTextMsg.setContent("系统出现错误，请与管理员联系！");

                replyMsg = WeixinUtils.msg2Xml(replyTextMsg);

                // 安全模式
                if (encryptFlag) {
                    replyMsg = WeixinUtils.encryptMsg(replyMsg, timestamp, nonce);
                }
            }
        }

        return replyMsg;
    }
}